home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / d / dos-edit.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  11.1 KB  |  404 lines

  1. ;    DOS-EDIT.ASM -- Resident DOS Command Line Editor
  2.  
  3. ;    ================================================
  4.  
  5.  
  6.  
  7. CSEG        Segment
  8.  
  9.         Assume    CS:CSEG
  10.  
  11.  
  12.  
  13.         Org    0080h
  14.  
  15. KeyboardBuffer    Label    Byte
  16.  
  17.  
  18.  
  19.         Org    0100h
  20.  
  21. Entry:        Jmp    Initialize
  22.  
  23.  
  24.  
  25. ;    All Data
  26.  
  27. ;    --------
  28.  
  29.  
  30.  
  31.         db    "(C) Copyright 1985 Ziff-Davis Publishing Co."
  32.  
  33.  
  34.  
  35. OldInterrupt21    dd    ?        ; Original Interrupt 21 vector
  36.  
  37. OldInterrupt16    dd    ?        ; Original Interrupt 16 vector
  38.  
  39. DoingBuffKey    db    0        ; Flag for doing Function Call 0Ah
  40.  
  41. BufferPointer    dw    KeyboardBuffer    ; Pointer to Keyboard Buffer
  42.  
  43. BufferCounter    db    0        ; Number of characters in buffer
  44.  
  45. MaxCharCol    db    ?        ; Maximum Character Column on screen
  46.  
  47. OriginalCursor    dw    ?        ; Place to save cursor on full-screen
  48.  
  49. InsertOn    db    0        ; Insert mode flag
  50.  
  51.  
  52.  
  53. KeyRoutine    dw    Home,Up,PgUp,Dummy,Left,Dummy,Right
  54.  
  55.         dw    Dummy,End,Down,PgDn,Insert,Delete
  56.  
  57.  
  58.  
  59. ;    New Interrupt 21 (DOS Function Calls)
  60.  
  61. ;    -------------------------------------
  62.  
  63.  
  64.  
  65. NewInterrupt21    Proc    Far
  66.  
  67.  
  68.  
  69.         Mov    CS:[DoingBuffKey],0    ; Turn flag off initially
  70.  
  71.  
  72.  
  73.         Cmp    AH,0Ah            ; Check if doing buffered input
  74.  
  75.         Jz    BufferedInput
  76.  
  77.  
  78.  
  79.         Jmp    CS:[OldInterrupt21]    ; If not, do regular interrupt
  80.  
  81.  
  82.  
  83. BufferedInput:    Mov    CS:[DoingBuffKey],-1    ; If so, turn on flag
  84.  
  85.  
  86.  
  87.         PushF                ; Simulate regular interrupt
  88.  
  89.         Call    CS:[OldInterrupt21]
  90.  
  91.  
  92.  
  93.         Mov    CS:[DoingBuffKey],0    ; Turn off flag
  94.  
  95.         Mov    CS:[BufferCounter],0    ; Re-set character counter
  96.  
  97.  
  98.  
  99.         IRet                ; Return to user program
  100.  
  101.  
  102.  
  103. NewInterrupt21    EndP
  104.  
  105.  
  106.  
  107. ;    New Interrupt 16 (BIOS Keyboard Routine)
  108.  
  109. ;    ----------------------------------------
  110.  
  111.  
  112.  
  113. NewInterrupt16    Proc    Far
  114.  
  115.  
  116.  
  117.         Sti                ; Re-enable interrupts
  118.  
  119.         Cmp    CS:[DoingBuffKey],0    ; Check if doing call 0Ah
  120.  
  121.         Jz    DoNotIntercept        ; If not, do old interrupt
  122.  
  123.  
  124.  
  125.         Cmp    CS:[BufferCounter],0    ; Check if chars in buffer
  126.  
  127.         Jnz    Substitute        ; If so, get them out
  128.  
  129.  
  130.  
  131.         Cmp    AH,0            ; See if doing a get key
  132.  
  133.         Jz    CheckTheKey        ; If so, get the key
  134.  
  135.  
  136.  
  137. DoNotIntercept:    Jmp    CS:[OldInterrupt16]    ; Otherwise, do old interrupt
  138.  
  139.  
  140.  
  141. CheckTheKey:    PushF                ; Save flags
  142.  
  143.         Call    CS:[OldInterrupt16]    ; Do regular interrupt
  144.  
  145.  
  146.  
  147.         Cmp    AX,4800h        ; Check if up cursor
  148.  
  149.         Jnz    NotTriggerKey        ; If not, don't bother 
  150.  
  151.  
  152.  
  153.         Call    FullScreen        ; Move around the screen
  154.  
  155.  
  156.  
  157.         Cmp    CS:[BufferCounter],0    ; Any chars to deliver?
  158.  
  159.         Jz    CheckTheKey        ; If not, get another key
  160.  
  161.  
  162.  
  163. ReturnBuffer:    Call    GetBufferChar        ; Otherwise, pull one out
  164.  
  165.  
  166.  
  167.         Inc    CS:[BufferPointer]    ; Kick up the pointer
  168.  
  169.         Dec    CS:[BufferCounter]    ; And knock down the counter
  170.  
  171.  
  172.  
  173. NotTriggerKey:    IRet                ; And go back to calling prog
  174.  
  175.  
  176.  
  177. ;    Substitute Key from Buffer
  178.  
  179. ;    --------------------------
  180.  
  181.  
  182.  
  183. Substitute:    Cmp    AH,2            ; See if shift status check
  184.  
  185.         Jae    DoNotIntercept        ; If so, can't be bothered
  186.  
  187.  
  188.  
  189.         Cmp    AH,0            ; See if get a key
  190.  
  191.         Jz    ReturnBuffer        ; If so, get the key above
  192.  
  193.  
  194.  
  195.         Call    GetBufferChar        ; Otherwise get a key
  196.  
  197.         Cmp    CS:[BufferCounter],0    ; And clear zero flag
  198.  
  199.  
  200.  
  201.         Ret    2            ; Return with existing flags
  202.  
  203.  
  204.  
  205. NewInterrupt16    EndP
  206.  
  207.  
  208.  
  209. ;    Get Buffer Character
  210.  
  211. ;    --------------------
  212.  
  213.  
  214.  
  215. GetBufferChar:    Push    BX        
  216.  
  217.         Mov    BX,CS:[BufferPointer]    ; Get pointer to key buffer
  218.  
  219.         Mov    AL,CS:[BX]        ; Get the key
  220.  
  221.         Sub    AH,AH            ; Blank out scan code
  222.  
  223.         Pop    BX
  224.  
  225.         Ret
  226.  
  227.  
  228.  
  229. ;    Full Screen Routine
  230.  
  231. ;    -------------------
  232.  
  233.  
  234.  
  235. FullScreen:    Push    AX            ; Save all these registers
  236.  
  237.         Push    BX
  238.  
  239.         Push    CX
  240.  
  241.         Push    DX
  242.  
  243.         Push    DI
  244.  
  245.         Push    DS
  246.  
  247.         Push    ES
  248.  
  249.  
  250.  
  251.         Mov    AX,CS            ; Set AX to this segment
  252.  
  253.         Mov    DS,AX            ; Do DS is this segment
  254.  
  255.         Mov    ES,AX            ; And ES is also
  256.  
  257.  
  258.  
  259.         Assume    DS:CSEG, ES:CSEG    ; Tell the assembler
  260.  
  261.  
  262.  
  263.         Mov    AH,0Fh            ; Get Video State
  264.  
  265.         Int    10h            ;   through BIOS
  266.  
  267.         Dec    AH            ; Number of columns on screen
  268.  
  269.         Mov    [MaxCharCol],AH        ; Save maximum column
  270.  
  271.                         ; BH = Page Number throughout
  272.  
  273.         Mov    AH,03h            ; Get cursor in DX
  274.  
  275.         Int    10h            ;   through BIOS
  276.  
  277.         Mov    [OriginalCursor],DX    ; And save the cursor position
  278.  
  279.  
  280.  
  281.         Call    Up            ; Move cursor up    
  282.  
  283.  
  284.  
  285. MainLoop:    Cmp    DH,Byte Ptr [OriginalCursor + 1]    ; If at line
  286.  
  287.         Jz    TermFullScreen        ; stated from, terminate
  288.  
  289.  
  290.  
  291.         Mov    AH,02h            ; Set cursor from DX
  292.  
  293.         Int    10h            ;   through BIOS
  294.  
  295.  
  296.  
  297. GetKeyboard:    Mov    AH,0            ; Get the next key
  298.  
  299.         PushF                ; By simulating Interrupt 16h
  300.  
  301.         Call    CS:[OldInterrupt16]    ;   which goes to BIOS
  302.  
  303.  
  304.  
  305.         Cmp    AL,1Bh            ; See if Escape key
  306.  
  307.         Jz    TermFullScreen        ; If so, terminate full screen
  308.  
  309.  
  310.  
  311. ;    Back Space
  312.  
  313. ;    ----------
  314.  
  315.  
  316.  
  317.         Cmp    AL,08h            ; See if back space
  318.  
  319.         Jnz    NotBackSpace        ; If not, continue test
  320.  
  321.  
  322.  
  323.         Or    DL,DL            ; Check if cursor at left
  324.  
  325.         Jz    MainLoop        ; If so, do nothing    
  326.  
  327.  
  328.  
  329.         Dec    DL            ; Otherwise, move cursor back
  330.  
  331.         Call    ShiftLeft        ; And shift line to the left
  332.  
  333.  
  334.  
  335.         Jmp    MainLoop        ; And continue for next key
  336.  
  337.  
  338.  
  339. ;    Carriage Return
  340.  
  341. ;    ---------------
  342.  
  343.  
  344.  
  345. NotBackSpace:    Cmp    AL,0Dh            ; See if Carriage Return
  346.  
  347.         Jnz    NotCarrRet        ; If not, continue test
  348.  
  349.  
  350.  
  351.         Call    End            ; Move line into buffer
  352.  
  353.  
  354.  
  355.         Mov    AL,0Dh            ; Tack on a Carriage Return
  356.  
  357.         Stosb                ; By writing to buffer
  358.  
  359.         Inc    [BufferCounter]        ; One more character in buffer
  360.  
  361.  
  362.  
  363.         Jmp    MainLoop        ; And continue
  364.  
  365.  
  366.  
  367. ;    Normal Character
  368.  
  369. ;    ----------------
  370.  
  371.  
  372.  
  373. NotCarrRet:    Cmp    AL,' '            ; See if normal character
  374.  
  375.         Jb    NotNormalChar        ; If not, continue test
  376.  
  377.  
  378.  
  379.         Cmp    [InsertOn],0        ; Check for Insert mode
  380.  
  381.         Jz    OverWrite        ; If not, overwrite 
  382.  
  383.  
  384.  
  385.         Call    ShiftRight        ; Shift line right for insert
  386.  
  387.         Jmp    Short NormalCharEnd    ; And get ready to print
  388.  
  389.  
  390.  
  391. OverWrite:    Mov    CX,1            ; Write one character
  392.  
  393.         Mov    AH,0Ah            ; By calling BIOS
  394.  
  395.         Int    10h
  396.  
  397.  
  398.  
  399. NormalCharEnd:    Call    Right            ; Cursor to right and print
  400.  
  401.  
  402.  
  403.         Jmp    MainLoop        ; Back for another key
  404.  
  405.  
  406.  
  407. ;    Cursor Key, Insert, or Delete Subroutine
  408.  
  409. ;    ----------------------------------------
  410.  
  411.  
  412.  
  413. NotNormalChar:    Xchg    AL,AH            ; Put extended code in AL
  414.  
  415.         Sub    AX,71            ; See if it's a cursor key
  416.  
  417.         Jc    GetKeyboard        ; If not, no good
  418.  
  419.  
  420.  
  421.         Cmp    AX,12            ; Another check for cursor
  422.  
  423.         Ja    GetKeyboard        ; If not, skip it 
  424.  
  425.  
  426.  
  427.         Add    AX,AX            ; Double for index
  428.  
  429.         Mov    DI,AX            ;   into vector table
  430.  
  431.  
  432.  
  433.         Call    [KeyRoutine + DI]    ; Do the routine
  434.  
  435.  
  436.  
  437.         Jmp    MainLoop        ; Back for another key    
  438.  
  439.  
  440.  
  441. ;    Terminate Full Screen Movement
  442.  
  443. ;    ------------------------------
  444.  
  445.  
  446.  
  447. TermFullScreen:    Mov    DX,[OriginalCursor]    ; Set cursor to original
  448.  
  449.         Mov    AH,2            ; And set it
  450.  
  451.         Int    10h            ;   through BIOS
  452.  
  453.  
  454.  
  455.         Pop    ES            ; Restore all registers
  456.  
  457.         Pop    DS
  458.  
  459.         Pop    DI
  460.  
  461.         Pop    DX
  462.  
  463.         Pop    CX
  464.  
  465.         Pop    BX
  466.  
  467.         Pop    AX
  468.  
  469.  
  470.  
  471.         Ret                ; And return to New Int. 16h
  472.  
  473.  
  474.  
  475. ;    Cursor Movement
  476.  
  477. ;    ---------------
  478.  
  479.  
  480.  
  481. Home:        Mov    DL,Byte Ptr [OriginalCursor]    ; Move cursor to
  482.  
  483.         Ret                ; to original column
  484.  
  485.  
  486.  
  487. Up:        Or    DH,DH            ; Check if at top row
  488.  
  489.         Jz    UpEnd            ; If so, do nothing
  490.  
  491.         Dec    DH            ; If not, decrement row
  492.  
  493. UpEnd:        Ret
  494.  
  495.  
  496.  
  497. PgUp:        Sub    DL,DL            ; Move cursor to far left 
  498.  
  499.         Ret
  500.  
  501.  
  502.  
  503. Left:        Or    DL,DL            ; Check if cursor at far left
  504.  
  505.         Jnz    GoWest            ; If not, move it left
  506.  
  507.         Mov    DL,[MaxCharCol]        ; Move cursor to right
  508.  
  509.         Jmp    Up            ; And go up one line
  510.  
  511. GoWest:        Dec    DL            ; Otherwise, decrement column
  512.  
  513.         Ret
  514.  
  515.  
  516.  
  517. Right:        Cmp    DL,[MaxCharCol]        ; Check if cursor at far right
  518.  
  519.         Jb    GoEast            ; If not, move it right
  520.  
  521.         Sub    DL,DL            ; Set cursor to left of screen
  522.  
  523.         Jmp    Down            ; And go down one line
  524.  
  525. GoEast:        Inc    DL            ; Otherwise, increment column
  526.  
  527.         Ret
  528.  
  529.  
  530.  
  531. End:        Call    TransferLine        ; Move line to buffer
  532.  
  533.         Mov    DX,[OriginalCursor]    ; Set cursor to original
  534.  
  535.         Ret
  536.  
  537.  
  538.  
  539. Down:        Inc    DH            ; Move cursor down one row
  540.  
  541.         Ret
  542.  
  543.  
  544.  
  545. PgDn:        Mov    CL,[MaxCharCol]        ; Get last column on screen
  546.  
  547.         Inc    CL            ; Kick it up by one
  548.  
  549.         Sub    CL,DL            ; Subtract current column
  550.  
  551.         Sub    CH,CH            ; Set top byte to zero
  552.  
  553.         Mov    AL,' '            ; Character to write
  554.  
  555.         Mov    AH,0Ah            ; Write blanks to screen
  556.  
  557.         Int    10h            ;   through BIOS
  558.  
  559. Dummy:        Ret
  560.  
  561.  
  562.  
  563. ;    Insert and Delete
  564.  
  565. ;    -----------------
  566.  
  567.  
  568.  
  569. Insert:        Xor    [InsertOn],-1        ; Toggle the InsertOn flag
  570.  
  571.         Ret                ;   and return    
  572.  
  573.  
  574.  
  575. Delete:        Call    ShiftLeft         ; Shift cursor line left
  576.  
  577.         Ret                ;   and return
  578.  
  579.  
  580.  
  581. ;    Transfer Line on Screen to Keyboard Buffer
  582.  
  583. ;    ------------------------------------------
  584.  
  585.  
  586.  
  587. TransferLine:    Sub    CX,CX            ; Count characters in line
  588.  
  589.         Mov    DI,Offset KeyboardBuffer    ; Place to store 'em
  590.  
  591.         Mov    [BufferPointer],DI    ; Save that address
  592.  
  593.         Cld                ; String direction forward
  594.  
  595.  
  596.  
  597. GetCharLoop:    Mov    AH,02h            ; Set Cursor at DX
  598.  
  599.         Int    10h            ;   through BIOS
  600.  
  601.  
  602.  
  603.         Mov    AH,08h            ; Read Character & Attribute
  604.  
  605.         Int    10h            ;   through BIOS
  606.  
  607.  
  608.  
  609.         Stosb                ; Save the character
  610.  
  611.  
  612.  
  613.         Inc    CX            ; Increment the counter
  614.  
  615.         Inc    DL            ; Increment the cursor column
  616.  
  617.         Cmp    DL,[MaxCharCol]        ; See if at end of line yet
  618.  
  619.         Jbe    GetCharLoop        ; If not, continue
  620.  
  621.  
  622.  
  623.         Dec    DI            ; Points to end of string
  624.  
  625.         Mov    AL,' '            ; Character to search through
  626.  
  627.         Std                ; Searching backwards
  628.  
  629.         Repz    Scasb            ; Search for first non-blank
  630.  
  631.         Cld                ; Forward direction again
  632.  
  633.         Jz    SetBufferCount        ; If all blanks, skip down
  634.  
  635.  
  636.  
  637.         Inc    CL            ; Number of non-blanks
  638.  
  639.         Inc    DI            ; At last character
  640.  
  641. SetBufferCount:    Inc    DI            ; After last character
  642.  
  643.         Mov    [BufferCounter],CL    ; Save the character count
  644.  
  645.  
  646.  
  647.         Ret                ; Return from routine
  648.  
  649.  
  650.  
  651. ;    Shift Line One Space Right (For Insert)
  652.  
  653. ;    ---------------------------------------
  654.  
  655.  
  656.  
  657. ShiftRight:    Push    DX            ; Save original cursor
  658.  
  659.         Mov    DI,AX            ; Character to insert
  660.  
  661.  
  662.  
  663. ShiftRightLoop:    Call    ReadAndWrite        ; Read character and write
  664.  
  665.  
  666.  
  667.         Inc    DL            ; Kick up cursor column 
  668.  
  669.         Cmp    DL,[MaxCharCol]        ; Check if it's rightmost
  670.  
  671.         Jbe    ShiftRightLoop        ; If not, keep going
  672.  
  673.  
  674.  
  675.         Pop    DX            ; Get back original cursor
  676.  
  677.         Ret                ; And return from routine
  678.  
  679.  
  680.  
  681. ;    Shift Line One Space Left (For Delete)
  682.  
  683. ;    --------------------------------------
  684.  
  685.  
  686.  
  687. ShiftLeft:    Mov    DI,0020h        ; Blank at end
  688.  
  689.         Mov    BL,DL            ; Save cursor column
  690.  
  691.         Mov    DL,[MaxCharCol]        ; Set cursor to end of line
  692.  
  693.         
  694.  
  695. ShiftLeftLoop:    Call    ReadAndWrite        ; Read character and write
  696.  
  697.  
  698.  
  699.         Dec    DL            ; Kick down cursor column
  700.  
  701.         Cmp    DL,BL            ; See if at original yet
  702.  
  703.         Jge    ShiftLeftLoop        ; If still higher, keep going 
  704.  
  705.  
  706.  
  707.         Inc    DL            ; Put cursor back to original
  708.  
  709.         Ret                ; And return from routine
  710.  
  711.  
  712.  
  713. ;    Read and Write Character for Line Shifts
  714.  
  715. ;    ----------------------------------------
  716.  
  717.  
  718.  
  719. ReadAndWrite:    Mov    AH,2            ; Set Cursor from DX
  720.  
  721.         Int    10h            ;   through BIOS
  722.  
  723.  
  724.  
  725.         Mov    AH,08h            ; Read Character and Attribute
  726.  
  727.         Int    10h            ;   through BIOS
  728.  
  729.  
  730.  
  731.         Xchg    AX,DI            ; Switch with previous char
  732.  
  733.  
  734.  
  735.         Mov    CX,1            ; One character to write
  736.  
  737.         Mov    AH,0Ah            ; Write character only
  738.  
  739.         Int    10h            ;   through BIOS
  740.  
  741.  
  742.  
  743.         Ret                ; Return from Routine
  744.  
  745.  
  746.  
  747. ;    Initialization on Entry
  748.  
  749. ;    -----------------------
  750.  
  751.  
  752.  
  753. Initialize:    Sub    AX,AX            ; Make AX equal zero
  754.  
  755.         Mov    DS,AX            ; To point to vector segment
  756.  
  757.  
  758.  
  759.         Les    BX,dword ptr DS:[21h * 4]; Get and save Int. 21h
  760.  
  761.         Mov    Word Ptr CS:[OldInterrupt21],BX
  762.  
  763.         Mov    Word Ptr CS:[OldInterrupt21 + 2],ES
  764.  
  765.  
  766.  
  767.         Les    BX,dword ptr DS:[16h * 4]; Get and save Int. 16h
  768.  
  769.         Mov    Word Ptr CS:[OldInterrupt16],BX
  770.  
  771.         Mov    Word Ptr CS:[OldInterrupt16 + 2],ES
  772.  
  773.  
  774.  
  775.         Push    CS            ; Restore DS register
  776.  
  777.         Pop    DS            ;   by setting to CS
  778.  
  779.  
  780.  
  781.         Mov    DX,Offset NewInterrupt21
  782.  
  783.         Mov    AX,2521h        ; Set new Interrupt 21h
  784.  
  785.         Int    21h            ;   through DOS
  786.  
  787.  
  788.  
  789.         Mov    DX,Offset NewInterrupt16
  790.  
  791.         Mov    AX,2516h        ; Set new Interrupt 16h
  792.  
  793.         Int    21h            ;   through DOS
  794.  
  795.  
  796.  
  797.         Mov    DX,Offset Initialize    ; Number of bytes to stay
  798.  
  799.         Int    27h            ; Terminate & remain resident
  800.  
  801.  
  802.  
  803. CSEG        EndS
  804.  
  805.         End    Entry
  806.  
  807.